﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Reflection;

using IBatisNet.DataAccess;
using IBatisNet.DataAccess.DaoSessionHandlers;
using IBatisNet.DataAccess.Interfaces;
using IBatisNet.DataMapper;
using IBatisNet.DataMapper.Configuration.Statements;
using IBatisNet.DataMapper.MappedStatements;
using IBatisNet.DataMapper.Scope;

namespace WSS.Pub
{
    public class DBBase : IDao
    {
        // Fields
        private static Dictionary<string, DBBase> _instance = new Dictionary<string, DBBase>();



        // Methods
        public ISqlMapper BeginTransaction()
        {
            ISqlMapper sqlMap = this.GetSqlMap();
            sqlMap.BeginTransaction();
            return sqlMap;
        }

        public void CommitTransaction(ISqlMapper sqlMap)
        {
            sqlMap.CommitTransaction();
        }

        public void Execute(IEnumerable<DBState> batchStatements)
        {
            ISqlMapper sqlMap = this.GetSqlMap();
            try
            {
                sqlMap.BeginTransaction();
                foreach (DBState state in batchStatements)
                {
                    if (state.Type == ESqlType.INSERT)
                    {
                        sqlMap.Insert(state.Name, state.Param);
                    }
                    else if (state.Type == ESqlType.UPDATE)
                    {
                        sqlMap.Update(state.Name, state.Param);
                    }
                    else
                    {
                        sqlMap.Delete(state.Name, state.Param);
                    }
                }
                sqlMap.CommitTransaction();
            }
            catch (Exception exception)
            {
                sqlMap.RollBackTransaction();
                throw exception;
            }
        }

        public void Execute(IEnumerable<string> sqlStatements)
        {
            List<DBState> batchStatements = new List<DBState>();
            foreach (string str in sqlStatements)
            {
                string str2 = str;
                string str3 = str2.ToUpper().Trim();
                ESqlType iNSERT = ESqlType.INSERT;
                if (str3.StartsWith(ESqlType.INSERT.ToString()))
                {
                    iNSERT = ESqlType.INSERT;
                }
                else if (str3.StartsWith(ESqlType.UPDATE.ToString()))
                {
                    iNSERT = ESqlType.UPDATE;
                }
                else if (str3.StartsWith(ESqlType.DELETE.ToString()))
                {
                    iNSERT = ESqlType.DELETE;
                }
                DBState item = new DBState();
                item.Name = "ExecuteNoneQuery";
                item.Param = str2;
                item.Type = iNSERT;
                batchStatements.Add(item);
            }
            this.Execute(batchStatements);
        }

        public void Execute(string sqlStatement)
        {
            ISqlMapper sqlMap = this.GetSqlMap();
            string str = sqlStatement;
            string str2 = str.ToUpper().Trim();
            ESqlType iNSERT = ESqlType.INSERT;
            if (str2.StartsWith(ESqlType.INSERT.ToString()))
            {
                iNSERT = ESqlType.INSERT;
            }
            else if (str2.StartsWith(ESqlType.UPDATE.ToString()))
            {
                iNSERT = ESqlType.UPDATE;
            }
            else if (str2.StartsWith(ESqlType.DELETE.ToString()))
            {
                iNSERT = ESqlType.DELETE;
            }
            DBState state2 = new DBState();
            state2.Name = "ExecuteNoneQuery";
            state2.Param = str;
            state2.Type = iNSERT;
            DBState state = state2;
            if (iNSERT == ESqlType.INSERT)
            {
                sqlMap.Insert(state.Name, state.Param);
            }
            else if (iNSERT == ESqlType.UPDATE)
            {
                sqlMap.Update(state.Name, state.Param);
            }
            else
            {
                sqlMap.Delete(state.Name, state.Param);
            }
        }

        public int ExecuteDelete(string statementName, object parameterObject)
        {
            int num2;
            ISqlMapper sqlMap = this.GetSqlMap();
            DateTime now = DateTime.Now;
            try
            {
                num2 = sqlMap.Delete(statementName, parameterObject);
            }
            catch (Exception exception)
            {
                throw exception;
            }
            return num2;
        }

        public object ExecuteInsert(string statementName, object parameterObject)
        {
            object obj3;
            ISqlMapper sqlMap = this.GetSqlMap();
            DateTime now = DateTime.Now;
            try
            {
                obj3 = sqlMap.Insert(statementName, parameterObject);
            }
            catch (Exception exception)
            {
                throw exception;
            }
            return obj3;
        }

        public void ExecuteMsSqlStoredProcedure(string statementName, object parameterObject)
        {
            DateTime now = DateTime.Now;
            ISqlMapper sqlMap = this.GetSqlMap();
            try
            {
                sqlMap.QueryForObject(statementName, parameterObject);
            }
            catch
            {
                throw;
            }
        }

        public DataTable ExecuteMsSqlStoredProcedureWithOutputCursor(string statementName, object parameterObject)
        {
            DataTable table;
            DateTime now = DateTime.Now;
            ISqlMapper sqlMap = this.GetSqlMap();
            try
            {
                table = sqlMap.QueryForDataTable(statementName, parameterObject);
            }
            catch
            {
                throw;
            }
            return table;
        }

        public void ExecuteOracleStoredProcedureWithOutputCursor(string statementName, object parameterObject)
        {
            DateTime now = DateTime.Now;
            ISqlMapper sqlMap = this.GetSqlMap();
            try
            {
                sqlMap.OracleStoredProcedureWithOutputCursor(statementName, parameterObject);
            }
            catch
            {
                throw;
            }
        }

        public IDictionary<K, V> ExecuteQueryForDictionary<K, V>(string statementName, object parameterObject)
        {
            IDictionary<K, V> dictionary;
            ISqlMapper sqlMap = this.GetSqlMap();
            try
            {
                dictionary = sqlMap.QueryForDictionary<K, V>(statementName, parameterObject, "ROWNUM");
            }
            catch
            {
                throw;
            }
            return dictionary;
        }

        public IList<T> ExecuteQueryForList<T>(string statementName, object parameterObject)
        {
            IList<T> list2;
            ISqlMapper sqlMap = this.GetSqlMap();
            try
            {
                list2 = sqlMap.QueryForList<T>(statementName, parameterObject);
            }
            catch (Exception exception)
            {
                throw exception;
            }
            return list2;
        }

        public IList ExecuteQueryForList(string statementName, object parameterObject)
        {
            IList list;
            ISqlMapper sqlMap = this.GetSqlMap();
            try
            {
                list = sqlMap.QueryForList(statementName, parameterObject);
            }
            catch
            {
                throw;
            }
            return list;
        }

        public IList<T> ExecuteQueryForList<T>(string statementName, object parameterObject, int skipResults, int maxResults)
        {
            IList<T> list2;
            ISqlMapper sqlMap = this.GetSqlMap();
            DateTime now = DateTime.Now;
            try
            {
                list2 = sqlMap.QueryForList<T>(statementName, parameterObject, skipResults, maxResults);
            }
            catch (Exception exception)
            {
                throw exception;
            }
            return list2;
        }

        public IList ExecuteQueryForList(string statementName, object parameterObject, int skipResults, int maxResults)
        {
            IList list;
            ISqlMapper sqlMap = this.GetSqlMap();
            try
            {
                list = sqlMap.QueryForList(statementName, parameterObject, skipResults, maxResults);
            }
            catch
            {
                throw;
            }
            return list;
        }

        public IList<StrObjDict> ExecuteQueryForListWithTransaction(ISqlMapper sqlMap, string statementName, object parameterObject)
        {
            IList<StrObjDict> list;
            try
            {
                list = sqlMap.QueryForList<StrObjDict>(statementName, parameterObject);
            }
            catch
            {
                throw;
            }
            return list;
        }

        public T ExecuteQueryForObject<T>(string statementName, object parameterObject)
        {
            T local;
            ISqlMapper sqlMap = this.GetSqlMap();
            try
            {
                local = sqlMap.QueryForObject<T>(statementName, parameterObject);
            }
            catch
            {
                throw;
            }
            return local;
        }

        public object ExecuteQueryForObject(string statementName, object parameterObject)
        {
            object obj2;
            ISqlMapper sqlMap = this.GetSqlMap();
            try
            {
                obj2 = sqlMap.QueryForObject(statementName, parameterObject);
            }
            catch
            {
                throw;
            }
            return obj2;
        }

        public object ExecuteScalar(string statementName, object parameterObject)
        {
            object obj3;
            ISqlMapper sqlMap = this.GetSqlMap();
            DateTime now = DateTime.Now;
            try
            {
                obj3 = sqlMap.QueryScalar(statementName, parameterObject);
            }
            catch (Exception exception)
            {
                throw exception;
            }
            return obj3;
        }

        public void ExecuteStoredProcedureNoneQuery(string statementName, object parameterObject)
        {
            this.ExecuteUpdate(statementName, parameterObject);
        }

        public int ExecuteUpdate(string statementName, object parameterObject)
        {
            int num2;
            ISqlMapper sqlMap = this.GetSqlMap();
            DateTime now = DateTime.Now;
            try
            {
                num2 = sqlMap.Update(statementName, parameterObject);
            }
            catch (Exception exception)
            {
                throw exception;
            }
            return num2;
        }

        public void ExecuteWithTransaction(ISqlMapper sqlMap, IEnumerable<DBState> batchStatements)
        {
            try
            {
                foreach (DBState state in batchStatements)
                {
                    if (state.Type == ESqlType.INSERT)
                    {
                        sqlMap.Insert(state.Name, state.Param);
                    }
                    else if (state.Type == ESqlType.UPDATE)
                    {
                        sqlMap.Update(state.Name, state.Param);
                    }
                    else
                    {
                        sqlMap.Delete(state.Name, state.Param);
                    }
                }
            }
            catch
            {
                throw;
            }
        }

        public IDaoManager GetDaoManager(string name)
        {
            if (string.IsNullOrEmpty(name))
            {
                return DaoManager.GetInstance();
            }
            return DaoManager.GetInstance(name);
        }

        public IDbCommand GetDbCommand(ISqlMapper sqlMapper, string statementName, object paramObject)
        {
            IStatement statement = sqlMapper.GetMappedStatement(statementName).Statement;
            IMappedStatement mappedStatement = sqlMapper.GetMappedStatement(statementName);
            ISqlMapSession localSession = new SqlMapSession(sqlMapper);
            if (sqlMapper.LocalSession != null)
            {
                localSession = sqlMapper.LocalSession;
            }
            else
            {
                localSession = sqlMapper.OpenConnection();
            }
            RequestScope request = statement.Sql.GetRequestScope(mappedStatement, paramObject, localSession);
            mappedStatement.PreparedCommand.Create(request, localSession, statement, paramObject);
            IDbCommand command = localSession.CreateCommand(CommandType.Text);
            command.CommandText = request.IDbCommand.CommandText;
            return command;
        }

        private IDbCommand GetDbCommand(ISqlMapper sqlMapper, string statementName, StrObjDict paramObject, StrObjDict dictParam, IDictionary<string, ParameterDirection> dictParmDirection, CommandType cmdType)
        {
            if (cmdType == CommandType.Text)
            {
                return this.GetDbCommand(sqlMapper, statementName, paramObject);
            }
            IStatement statement = sqlMapper.GetMappedStatement(statementName).Statement;
            IMappedStatement mappedStatement = sqlMapper.GetMappedStatement(statementName);
            ISqlMapSession localSession = new SqlMapSession(sqlMapper);
            if (sqlMapper.LocalSession != null)
            {
                localSession = sqlMapper.LocalSession;
            }
            else
            {
                localSession = sqlMapper.OpenConnection();
            }
            RequestScope request = statement.Sql.GetRequestScope(mappedStatement, paramObject, localSession);
            mappedStatement.PreparedCommand.Create(request, localSession, statement, paramObject);
            IDbCommand command = localSession.CreateCommand(cmdType);
            command.CommandText = request.IDbCommand.CommandText;
            if ((cmdType == CommandType.StoredProcedure) && (dictParam != null))
            {
                foreach (KeyValuePair<string, object> pair in dictParam)
                {
                    string key = pair.Key.ToString();
                    IDbDataParameter parameter = command.CreateParameter();
                    parameter.ParameterName = key;
                    parameter.Value = pair.Value;
                    if ((dictParmDirection != null) && dictParmDirection.ContainsKey(key))
                    {
                        parameter.Direction = dictParmDirection[key];
                    }
                    command.Parameters.Add(parameter);
                }
            }
            return command;
        }

        public string GetDbtype()
        {
            IDaoManager instance = null;
            if (string.IsNullOrEmpty(this.ContextName))
            {
                instance = DaoManager.GetInstance();
            }
            else
            {
                instance = DaoManager.GetInstance(this.ContextName);
            }
            return instance.LocalDataSource.DbProvider.Name;
        }

        public static DBBase getInstance()
        {
            if (!_instance.ContainsKey("DEFAULT"))
            {
                _instance["DEFAULT"] = new DBBase();
                _instance["DEFAULT"].ContextName = null;
            }
            return _instance["DEFAULT"];
        }

        public static DBBase getInstance(string as_ContextName)
        {
            string key = "";
            if ((as_ContextName == "") || (as_ContextName == null))
            {
                key = "DEFAULT";
            }
            else
            {
                key = as_ContextName;
            }
            if (!_instance.ContainsKey(key))
            {
                _instance[key] = new DBBase();
                _instance[key].ContextName = as_ContextName;
            }
            return _instance[key];
        }

        public string GetSql(string statementName, object paramObject, bool isPremitive)
        {
            ISqlMapper sqlMap = this.GetSqlMap();
            try
            {
                
                return sqlMap.ExtractSql(statementName, paramObject, isPremitive);
            }
            catch
            {
                return "";
            }
        }

        public ISqlMapper GetSqlMap()
        {
            IDaoManager instance = null;
            if (string.IsNullOrEmpty(this.ContextName))
            {
                instance = DaoManager.GetInstance();
            }
            else
            {
                instance = DaoManager.GetInstance(this.ContextName);
            }
            SqlMapDaoSession sqlMapDaoSession = instance.GetDaoSession() as SqlMapDaoSession;
            if (sqlMapDaoSession != null)
            {
                ISqlMapper sqlMap = sqlMapDaoSession.SqlMap;
                if (!string.IsNullOrEmpty(this.ConnectString))
                {
                    sqlMap.DataSource.ConnectionString = this.ConnectString;
                }
                return sqlMap;
            }
            return null;
        }

        public string GetType(ESqlType type)
        {
            if (type == ESqlType.INSERT)
            {
                return "INSERT";
            }
            if (type == ESqlType.UPDATE)
            {
                return "UPDATE";
            }
            if (type == ESqlType.DELETE)
            {
                return "DELETE";
            }
            return "SELECT";
        }

        public DataTable QueryForDataTable(string statementName, object paramObject)
        {
            DataTable table;
            ISqlMapper sqlMap = this.GetSqlMap();
            bool flag = false;
            DateTime now = DateTime.Now;
            try
            {
                if (!sqlMap.IsSessionStarted)
                {
                    sqlMap.OpenConnection();
                    flag = true;
                }
                DataSet dataSet = new DataSet();
                IMappedStatement mappedStatement = sqlMap.GetMappedStatement(statementName);
                RequestScope request = mappedStatement.Statement.Sql.GetRequestScope(mappedStatement, paramObject, sqlMap.LocalSession);
                mappedStatement.PreparedCommand.Create(request, sqlMap.LocalSession, mappedStatement.Statement, paramObject);
                using (IDbCommand command = (IDbCommand)request.IDbCommand.GetType().GetField("_innerDbCommand", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(request.IDbCommand))
                {
                    int num = sqlMap.LocalSession.CreateDataAdapter(command).Fill(dataSet);
                }
                table = dataSet.Tables[0];
            }
            catch (Exception exception)
            {
                throw exception;
            }
            finally
            {
                if (flag)
                {
                    sqlMap.CloseConnection();
                }
            }
            return table;
        }

        public DataTable QueryForDataTable(string statementName, object paramObject, IDictionary<string, object> outputParameters)
        {
            DataTable table;
            ISqlMapper sqlMap = this.GetSqlMap();
            try
            {
                table = sqlMap.QueryForDataTable(statementName, paramObject, outputParameters);
            }
            catch
            {
                throw;
            }
            return table;
        }

        public DataTable QueryForDataTable(string statementName, StrObjDict paramObject, StrObjDict dictParam, IDictionary<string, ParameterDirection> dictParamDirection, out Hashtable htOutPutParameter)
        {
            ISqlMapper sqlMap = this.GetSqlMap();
            DataSet dataSet = new DataSet();
            bool flag = false;
            ISqlMapSession localSession = sqlMap.LocalSession;
            if (localSession == null)
            {
                localSession = new SqlMapSession(sqlMap);
                localSession.OpenConnection();
                flag = true;
            }
            IDbCommand command = this.GetDbCommand(sqlMap, statementName, paramObject, dictParam, dictParamDirection, CommandType.StoredProcedure);
            try
            {
                command.Connection = localSession.Connection;
                localSession.CreateDataAdapter(command).Fill(dataSet);
            }
            finally
            {
                if (flag)
                {
                    localSession.CloseConnection();
                }
            }
            htOutPutParameter = new Hashtable();
            foreach (IDataParameter parameter in command.Parameters)
            {
                if (parameter.Direction == ParameterDirection.Output)
                {
                    htOutPutParameter[parameter.ParameterName] = parameter.Value;
                }
            }
            return dataSet.Tables[0];
        }

        public void RollBackTransaction(ISqlMapper sqlMap)
        {
            sqlMap.RollBackTransaction();
        }



        // Properties
        private string ConnectString { get; set; }

        private string ContextName { get; set; }

    }

}